// Mobile Shell 3 Toggler
// Copyright (C) 2009, Avian Waves Software
// Licensed under Ms-Rl

#include <Shellapi.h>
#include <Tlhelp32.h>
#pragma comment (lib,"toolhelp.lib") 

#define TH32CS_SNAPNOHEAPS 0x40000000 

extern HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags, DWORD th32ProcessID);
extern BOOL WINAPI CloseToolhelp32Snapshot(HANDLE hSnapshot);

DWORD GetPIDByProcName(wchar_t *procName)
{
  DWORD pid = 0;
  PROCESSENTRY32 pe32 = {0}; 

  HANDLE thh = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | TH32CS_SNAPNOHEAPS, 0);

  if (thh != (HANDLE) -1)
  {
    pe32.dwSize = sizeof(PROCESSENTRY32);
    if (Process32First(thh, &pe32)) 
    { 
      do 
      { 
        if (!_wcsicmp(pe32.szExeFile,procName)) 
        { 
          pid = pe32.th32ProcessID;
          break;
        } 
      } 
      while (Process32Next(thh, &pe32)); 
    }

    CloseToolhelp32Snapshot(thh);
  }
  
  return pid;
}

HWND FindFirstManilaHwndByClass(wchar_t *mclass)
{
  DWORD mpid = GetPIDByProcName(L"MobileShell.exe");
  HWND hwnd;

  if (mpid > 0)
  {
    hwnd = GetForegroundWindow();
    hwnd = GetWindow(hwnd, GW_HWNDFIRST);

    while (hwnd != NULL)
    {
      wchar_t pclass[201] = {0};
      GetClassName(hwnd, pclass, 200);
      
      if (!_wcsicmp(mclass, pclass)) 
      { 
        DWORD pid = 0;
        GetWindowThreadProcessId(hwnd, &pid);

        if (pid == mpid)
        {
          return hwnd;
        }
      } 

      hwnd = GetWindow(hwnd, GW_HWNDNEXT);
    }
  }

  return NULL;
}

HWND FindFirstSenseHwndByClass(wchar_t *mclass)
{
  DWORD mpid = GetPIDByProcName(L"manila.exe");
  HWND hwnd;

  if (mpid > 0)
  {
    hwnd = GetForegroundWindow();
    hwnd = GetWindow(hwnd, GW_HWNDFIRST);

    while (hwnd != NULL)
    {
      wchar_t pclass[201] = {0};
      GetClassName(hwnd, pclass, 200);
      
      if (!_wcsicmp(mclass, pclass)) 
      { 
        DWORD pid = 0;
        GetWindowThreadProcessId(hwnd, &pid);

        if (pid == mpid)
        {
          return hwnd;
        }
      } 

      hwnd = GetWindow(hwnd, GW_HWNDNEXT);
    }
  }

  return NULL;
}

BOOL GetInstallDir(wchar_t *data, BOOL leadingQuote)
{
  HKEY hkey;
  DWORD length = MAX_PATH * sizeof(wchar_t);
  BOOL ret = FALSE;

  DWORD type = REG_SZ;
  DWORD disp;

  wchar_t data2[MAX_PATH];

  if (RegCreateKeyEx(HKEY_LOCAL_MACHINE, L"Software\\Spb Software House 2\\Spb Mobile Shell", 0, 0, 0, 0, 0, &hkey, &disp) == ERROR_SUCCESS)
  {
    if (RegQueryValueEx(hkey, L"InstallDir", 0, &type, (LPBYTE)data2, &length) == ERROR_SUCCESS)
    {
      if (leadingQuote)
      {
        wcsncpy(data, L"\"", MAX_PATH);
      }
      else
      {
        wcsncpy(data, L"", MAX_PATH);
      }

      wcsncat(data, data2, MAX_PATH);

      ret = TRUE;
    }

    RegCloseKey(hkey);
  }

  return ret;
}

// Show MS3!
void ShowMS3()
{
  HideSense();


  // Find message window
  //HWND hwnd = FindWindow(L"SpbNow_MainWindow", L"");

  //if (hwnd != NULL)
  //{
    //SendMessage(hwnd, 0x8258, 1, 0);

  //}
  //else // launch MS3 since it is not running right now
  //{
  wchar_t path[MAX_PATH];
  
  if (GetInstallDir(path, FALSE))
  {
    PROCESS_INFORMATION pi;

    wcsncat(path, L"\\MenuLauncher.exe", MAX_PATH);

    if (!CreateProcess(path, 0, 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, 0, &pi))
    {
      DWORD err = GetLastError();

      switch (err)
      {
      case ERROR_FILE_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_FILE_NOT_FOUND",L"",0);
        break;
      case ERROR_PATH_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_PATH_NOT_FOUND",L"",0);
        break;
      case ERROR_DDE_FAIL:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_DDE_FAIL",L"",0);
        break;
      case ERROR_NO_ASSOCIATION:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_NO_ASSOCIATION",L"",0);
        break;
      case ERROR_ACCESS_DENIED:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_ACCESS_DENIED",L"",0);
        break;
      case ERROR_DLL_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_DLL_NOT_FOUND",L"",0);
        break;
      case ERROR_CANCELLED:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_CANCELLED",L"",0);
        break;
      case ERROR_NOT_ENOUGH_MEMORY:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_NOT_ENOUGH_MEMORY",L"",0);
        break;
      case ERROR_SHARING_VIOLATION:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_SHARING_VIOLATION",L"",0);
        break;
      default:
        MessageBox(0,L"Could not launch Mobile Shell 3: UNKNOWN ERROR",L"",0);
        break;
      }
    }
  }
  //}

  // Show the desktop
  //SetForegroundWindow(GetDesktopWindow());
}

// Hide MS3!
void HideMS3()
{
  // Find message window
  //HWND hwnd = FindWindow(L"SpbNow_MainWindow", L"");
  //SendMessage(hwnd, 0x82BC, 1, 0);

  // Show the desktop
  //SetForegroundWindow(GetDesktopWindow());

  wchar_t path[MAX_PATH];
  wchar_t cmdline[MAX_PATH];
  
  if (GetInstallDir(path, FALSE))
  {
    PROCESS_INFORMATION pi;

    wcsncat(path, L"\\MenuLauncher.exe", MAX_PATH); 
    wcsncpy(cmdline, L"\"", MAX_PATH);
    wcsncat(cmdline, path, MAX_PATH);
    wcsncat(cmdline, L"\" -cmd:\"menu|Tools\\Show Today\"", MAX_PATH);

    if (!CreateProcess(path, cmdline, 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, 0, &pi))
    {
      DWORD err = GetLastError();

      switch (err)
      {
      case ERROR_FILE_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_FILE_NOT_FOUND",L"",0);
        break;
      case ERROR_PATH_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_PATH_NOT_FOUND",L"",0);
        break;
      case ERROR_DDE_FAIL:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_DDE_FAIL",L"",0);
        break;
      case ERROR_NO_ASSOCIATION:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_NO_ASSOCIATION",L"",0);
        break;
      case ERROR_ACCESS_DENIED:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_ACCESS_DENIED",L"",0);
        break;
      case ERROR_DLL_NOT_FOUND:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_DLL_NOT_FOUND",L"",0);
        break;
      case ERROR_CANCELLED:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_CANCELLED",L"",0);
        break;
      case ERROR_NOT_ENOUGH_MEMORY:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_NOT_ENOUGH_MEMORY",L"",0);
        break;
      case ERROR_SHARING_VIOLATION:
        MessageBox(0,L"Could not launch Mobile Shell 3: ERROR_SHARING_VIOLATION",L"",0);
        break;
      default:
        MessageBox(0,L"Could not launch Mobile Shell 3: UNKNOWN ERROR",L"",0);
        break;
      }
    }
  }

  RestoreSense();
}


void RestoreSense()
{

}

void HideSense()
{

}


// Close MS3!
void CloseMS3()
{
  DWORD pid = GetPIDByProcName(L"MobileShell.exe");

  if (pid > 0)
  {
    HANDLE proc = OpenProcess(0, FALSE, pid);

    if (proc != NULL)
    {
      TerminateProcess(proc, 0);
    }
  }

  // Restore Sense if we hid it previously
  RestoreSense();

  // Show the MS3less desktop
  SetForegroundWindow(GetDesktopWindow());
}

// Toggle MS3!
void ToggleMS3()
{
  HWND manila = FindFirstManilaHwndByClass(L"SpbNow_HomeWindow");

  if (manila == NULL)
  {
    manila = FindFirstManilaHwndByClass(L"Manila");
  }
  
  if (manila != NULL && IsWindowVisible(manila))
  {
//    MessageBox(0,L"HIDE",L"",0);
    HideMS3();
  }
  else // otherwise, show it!
  {
//    MessageBox(0,L"SHOW",L"",0);
    ShowMS3();
  }
}

void SmartToggleMS3()
{
  HWND fg = GetForegroundWindow();
  HWND desk = GetDesktopWindow();
  HWND manila = FindFirstManilaHwndByClass(L"SpbNow_HomeWindow");
  HWND sense = FindFirstSenseHwndByClass(L"Manila");

  if (manila == NULL)
  {
    manila = FindFirstManilaHwndByClass(L"Manila");
  }

  if (fg == desk || (manila != NULL && fg == manila) || (sense != NULL && fg == sense))
  {
    MessageBox(0,L"TOGGLE",L"",0);
    ToggleMS3();
  }
  else if (manila != NULL && IsWindowVisible(manila))
  {
    MessageBox(0,L"SHOW",L"",0);
    ShowMS3();
  }
  else
  {
    MessageBox(0,L"HIDE",L"",0);
    SetForegroundWindow(GetDesktopWindow());
  }
}

